package com.aegonthtf.sis.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;

/**
 * 事务管理切面
 *
 * @author huangjiangming@fulan.com.cn
 * @date 2021/3/31 17:43
 */
@Slf4j
@Aspect
@Component
@Order(99999)
public class TransactionAspect {

    private final static DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();

    static {
        // 创建事务隔离策略
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        defaultTransactionDefinition.setTimeout(30);
    }

    @Resource(type = DataSourceTransactionManager.class)
    private DataSourceTransactionManager dataSourceTransactionManager;

    /**
     * 对每个do接口进行事务管理
     *
     * @param joinPoint 切面入口
     * @return java.lang.Object
     * @author huangjiangming@fulan.com.cn
     * @date 2021/3/31 17:43
     */
    @Around("execution(* com.aegonthtf.sis..controller..do*(..))")
    public Object controller(ProceedingJoinPoint joinPoint) throws Throwable {
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(defaultTransactionDefinition);

        boolean result = false;
        Object obj;
        try {
            obj = joinPoint.proceed();
            dataSourceTransactionManager.commit(transactionStatus);
            result = true;
        } catch (Throwable throwable) {
            dataSourceTransactionManager.rollback(transactionStatus);
            Signature signature = joinPoint.getSignature();
            String methodName = signature.getName();
            String simpleClassName = signature.getDeclaringType().getSimpleName();
            log.error(String.format("调用【%s】类的【%s】方法， 发送事务异常: %s", simpleClassName, methodName, throwable));
            throw throwable;
        } finally {
            log.info("transaction:{} -> {}", joinPoint.toString(), result);
        }
        return obj;
    }

}
